﻿using System.IO;
using System.Linq;
using System.Text;
using UnityEditor;
using UnityEditor.Animations;
using UnityEngine;

namespace WentStateMachine
{
    public class StateScriptsGenerator
    {
        AnimatorController animatorController;

        private readonly string namespaceString;
        public StateScriptsGenerator(AnimatorController animatorController, string namespaceStr)
        {
            this.animatorController = animatorController;
            this.namespaceString = namespaceStr;
        }

        public void Generate()
        {
            foreach (var layer in animatorController.layers)
            {
                if (layer == null)
                    continue;

                foreach (var state in layer.stateMachine.states)
                {
                    var wentStateMachineBehaviour = state.state.behaviours.ToList().Find(x=>x is WentStateMachineBehaviour) as WentStateMachineBehaviour;

                    if (wentStateMachineBehaviour == null)
                    {
                        Debug.LogWarning($"Add WentStateMachineBehaviour for {state.state.name} first!");
                        continue;
                        // wentStateMachineBehaviour = state.state.AddStateMachineBehaviour(typeof(WentStateMachineBehaviour)) as WentStateMachineBehaviour;
                    }

                    if (wentStateMachineBehaviour.StateBehaviour != null
                        && GetClassName(wentStateMachineBehaviour.StateBehaviour) == state.state.name)
                    {
                        continue;
                    }
                    CreateScriptFile(animatorController, state.state.name, GenerateScriptCode(state));
                }
            }

        }

        string GetClassName(StateBehaviour stateBehaviour)
        {
            return stateBehaviour.GetType().Name;
        }
        string GenerateScriptCode(ChildAnimatorState state)
        {
            StringBuilder sb = new StringBuilder();

            sb.AppendLine("using System.Collections;\r\nusing UnityEngine;\r\nusing WentStateMachine;\r\n");

            sb.AppendLine($"namespace {namespaceString}");

            sb.AppendLine("{");

            sb.AppendLine($"[State(DisplayName = \"{namespaceString}/{state.state.name}\")]");
            sb.AppendLine($"public class {state.state.name}State : StateBehaviour");
            sb.AppendLine("{");
            sb.AppendLine("}");

            sb.AppendLine("}");
            return sb.ToString();
        }

        void CreateScriptFile(AnimatorController controller, string stateName, string script)
        {
            var className = stateName + "State";
            string path = Application.dataPath;
            path = path.Remove(path.Length - "Assets".Length);
            path += AssetDatabase.GetAssetPath(animatorController);
            var controllerFile = Path.GetFileName(path);
            path = path.Replace(controllerFile, "");
            path += $"{className}.cs";
            if (File.Exists(path))
            {
                Debug.LogWarning($"StateMachineFile:{className}.cs already exists!");
                return;
            }

            using (FileStream fs = new FileStream(path, FileMode.Create))
            {
                StreamWriter sw = new StreamWriter(fs);
                sw.Write(script);
                sw.Flush();
            }

            Debug.Log($"StateMachineFile: <color=blue>{className}.cs</color> now create!");
        }
    }
}